﻿// CMatrix.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include"CMatrix.h"
//默认构造函数
CMatrix:: CMatrix(void)
	: _A(NULL)
	, _row(-1)
	, _column(-1)
{}
//构造函数一
CMatrix::CMatrix(int row, int column)
{
	_row = row;
	_column = column;
	_A = new double *[row];
	for (int i = 0; i < row; i++)
		_A[i] = new double[column];
	// Initialize
	for (int i = 0; i < row; i++)
		for (int j = 0; j < column; j++)
			_A[i][j] = 0.0f;
}
// 复制构造函数
CMatrix::CMatrix(const CMatrix& m) {
	_row = m._row;
	_column = m._column;
	_A = new double *[_row];
	for (int i = 0; i < _row; i++)
		_A[i] = new double[_column];
	for (int i = 0; i < _row; i++)
	{
		for (int j=0;j<_column;j++)
		{
         //
			_A[i][j] = m._A[i][j];



		}
	}
}
//默认析构函数
CMatrix::~CMatrix(void)
{
	if (NULL != _A)
	{
		for (int i = 0; i < _row; i++)
		{
			delete[] _A[i];//逐个删除
		}
			//if (NULL != _A)
				delete[] _A;
		
	}
}
			
// 赋值运算符
CMatrix& CMatrix::operator=(const CMatrix& m) 
{
	if (&m == this)
		return *this;
	// Added by ybwang at 2014/06/04
	if (NULL != _A)
	{
		for (int i = 0; i < _row; i++)
			delete[] _A[i];
		delete[] _A;
	}
	_row = m._row;
	_column = m._column;
	_A = new double *[_row];
	for (int i = 0; i < _row; i++)
		_A[i] = new double[_column];
	for (int i = 0; i < _row; i++)
	{
		for (int j = 0; j < _column; j++)
		{
			//赋值
			_A[i][j]=m._A[i][j];

		}
	}
	return *this;
}

//设置单位阵
bool CMatrix::setUnitMatrix()
{
	if (_row != _column)
		return false;
	for (int i = 0; i < _row; ++i)
	{
		for (int j = 0; j < _column; ++j)
		{
			if (i == j)
				_A[i][j] = 1.0f;
			else
				_A[i][j] = 0.0f;
		}
	}
	return true;
}


//比较运算符
bool CMatrix::operator==(const CMatrix& m)
{
if ((_row != m.getRow()) || (_column != m.getColumn()))
return false;
for (int i = 0; i < _row; i++ )
	for (int j = 0; j < _column; j++ )
		if (fabs(_A[i][j] - m.getValue(i,j)) > 10e-6)
			return false;
return true;
}
bool CMatrix::operator!=(const CMatrix& m)
{
	if ((_row != m.getRow()) || (_column != m.getColumn())) return true;
	for (int i = 0; i < _row; i++)
	{
		for (int j = 0; j < _column; j++)
		{
			if (fabs(_A[i][j] - m.getValue(i, j)) < 10e-6)
				continue;
			else
				return true;
		}
	}
	return false;
}
//加法运算符
CMatrix CMatrix::operator+(const CMatrix& m)
{
	assert(_row == m.getRow() && _column == m.getColumn());
	CMatrix result(_row, _column);
	for (int i = 0; i < _row; i++)
	{
		for (int j = 0; j < _column; j++)
		{
			result.setValue(i, j, _A[i][j] + m.getValue(i, j));
		}
	}
	return result;
}
//减法运算符
CMatrix CMatrix::operator-(const CMatrix& m)
{
	assert(_row == m.getRow() && _column == m.getColumn());
	CMatrix result(_row, _column);
	for (int i = 0; i < _row; i++ )
	{
		for(int j = 0; j < _column; j ++)
		{
			result.setValue(i, j, _A[i][j] - m.getValue(i, j));
		}
	}
	return result;
}
//自加运算符
CMatrix & CMatrix::operator +=(const CMatrix& m)
{
	assert(_row = m.getRow() && _column ==m.getColumn());
	for (int i = 0; i < _row; i++)
	{
		for (int j = 0; j < _column; j++)
		{_A[i][j] += m.getValue(i, j);
	}
	}
return *this;
}
//自减运算符
CMatrix& CMatrix::operator-=(const CMatrix& m)
{
assert(_row == m.getRow()&& _column == m.getColumn());
for(int i = 0; i < _row; i++ )
{
	for(int j = 0; j < _column; j ++)
		_A[i][j] -= m.getValue(i, j);
}
return *this;
}

//乘法运算
CMatrix CMatrix::operator*(const CMatrix& m)
{
	assert(_column == m.getRow());
	CMatrix result(m.getRow(), m.getColumn());//改正的地方
		for(int i = 0; i < _row; i ++ )
	{
		for(int j = 0; j < result.getColumn(); j ++ )
		{
			double value =0.0f;
			for (int k = 0; k < getColumn(); k++ ) // 这里之前出现了错误,已改正

				value+=getValue(i,k)*m.getValue(k,j);//矩阵乘法

				result.setValue(i, j, value);
		}
	}
	return result;
}
//矩阵数乘
CMatrix CMatrix::operator*(const double& s)
{
	CMatrix result(_row, _column);
	for (int i = 0; i < _row; ++i)
	{
		for (int j = 0; j < _column; ++j)
		{
			result.setValue(i, j, getValue(i, j) * s);
		}
	}
	return result;
}
			//单目运算符：取负
CMatrix CMatrix::operator-()
{
	CMatrix m(_row, _column);
	for (int i = 0; i < _row; i++) {
		for (int j = 0; j < _column; j++)
			m.setValue(i, j, -_A[i][j]);
	}
	return m;
}

//转置
CMatrix CMatrix::transpose()
{
	CMatrix m(_column, _row);
	for (int i = 0; i < _column; i++)
	{
		for(int j = 0; j < _row; j++)
		{
			m.setValue(i,j,getValue(j,i));
			
		}
	}
	return m;
}

//矩阵求逆(列主元素法)
CMatrix CMatrix::inverse()
{
	assert(_row == _column);
	CMatrix NXW(_row, _row * 2);
	//设置NXW的值
	for(int i = 0; i < _row; i++)
	{
		for (int j = 0; j < _row * 2; j++)
		{
			if (j < _row) NXW.setValue(i, j, getValue(i, j));
			else 
			{
				if (i==(j - _row))NXW.setValue(i,j,1.0f);
				else NXW.setValue(i, j, 0.0f);
			}
		}
	}

//用高斯•若当消去法求解平面方程的系数，只要对NTW进行消去即可求得系数 
	long kindex;
	double mk;//mk为列主元的值，kindex用于存储列主元所在的位置(行)
	double aiitem;//用于寻找列主元时临时存储最大值
for(int i=0;i<_row;i++)
{
	//选取列主元
	mk=NXW.getValue(i,i);
	kindex=-1;
	for (int j=i+1;j<_row;j++)
	{
		if (fabs(NXW.getValue(j, i)) > fabs(mk))// 需要考虑绝对值得情形
{
			mk = NXW.getValue(j, i);
			kindex = j;
 }
	}
//列主元选取完成
//交换行
	if(kindex!=-1)
	{
		for (int k = 0; k < _row * 2; k++)
		{
			aiitem = NXW.getValue(i, k);
			NXW.setValue(i, k, NXW.getValue(kindex, k));
			NXW.setValue(kindex,k,aiitem);
		}
	}
		//交换行完成
		//消去
	for (int k=0;k<_row * 2; k++)
		NXW.setValue(i,k,NXW.getValue(i,k)/mk);// 先置当前行的列主元为 1.0
		for(int k=0;k<_row;k++)
		{
			if (k==i)continue;
			double tem = NXW.getValue(k, i);// 因为 NXW[k][i]的值随时变化，所以必须设 置临时变量以保持该值
			for(int l=0;l<_row *2;l++)
			{
				NXW.setValue(k, l, NXW.getValue(k, l) - tem * NXW.getValue(i, l));
			}
		}
	}
CMatrix result(_row, _row);
		for(int i=0;i<_row;i++)
		{
			for (int j= 0;j<_row;j++)
			{
				result.setValue(i,j,NXW.getValue(i,j +_row));
			}
		}
		return result;
	}


// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
